/**
 * 
 */
package hr.fer.zemris.annotator.services;

import hr.fer.zemris.annotator.factories.CallGraphDataFactory;
import hr.fer.zemris.annotator.factories.MethodFactory;
import hr.fer.zemris.annotator.factories.MethodMappingDataFactory;
import hr.fer.zemris.annotator.model.Method;
import hr.fer.zemris.annotator.model.MethodData;
import hr.fer.zemris.annotator.model.interfaces.ICallGraphDataFactory;
import hr.fer.zemris.annotator.model.interfaces.IMethodFactory;
import hr.fer.zemris.annotator.model.interfaces.IMethodMappingDataFactory;
import hr.fer.zemris.annotator.model.profiling.CallGraphData;
import hr.fer.zemris.annotator.model.profiling.MethodMappingData;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author dajan
 * 
 */
public class ProfilingDataParsingService {

	public static MethodData parseGprofileOutput(String outputPath)
			throws IOException {

		BufferedReader reader = new BufferedReader(new FileReader(outputPath));
		List<Method> methodData = new ArrayList<Method>();
		List<CallGraphData> callGraphData = new ArrayList<CallGraphData>();
		List<MethodMappingData> methodMappingData = new ArrayList<MethodMappingData>();

		IMethodFactory methodFactory = MethodFactory.getInstance();
		ICallGraphDataFactory callGraphFactory = CallGraphDataFactory
				.getInstance();
		IMethodMappingDataFactory methodMappingDataFactory = MethodMappingDataFactory
				.getInstance();
		boolean flatData = false;
		boolean firstTimeFlatData = true;
		boolean graphData = false;
		boolean firstTimeGraphData = true;
		boolean callGraphDataLinesStarted = false;
		boolean createdGraphLines = false;
		String callGraphDataLines = "";
		boolean functionMapping = false;

		// nedo bog da ovo ide neko skontat.. -.-
		while (true) {

			String line = reader.readLine();
			if (line == null)
				break;
			line = line.trim();

			if (firstTimeFlatData) {
				if (line.startsWith("time")) {
					flatData = true;
					firstTimeFlatData = false;
					continue;
				}
			}

			if (line.equals("")) {
				flatData = false;
			}

			if (firstTimeGraphData) {
				if (line.equals("<spontaneous>") || line.startsWith("index % time    self  children")) {
					graphData = true;
					firstTimeGraphData = false;
					callGraphDataLinesStarted = true;
					continue;
				}
			}

			if (callGraphDataLinesStarted) {
				if (line.startsWith("---")) {
					createdGraphLines = true;
				} else if (line.equals("")) {

					continue;

				} else {
					callGraphDataLines += "#";
					callGraphDataLines += line;
					// continue;
				}

			}

			if (line.equals("")) {
				graphData = false;
				callGraphDataLinesStarted = false;
			}

			if (flatData) {
				methodData.add(methodFactory.getFlatMethodData(line));
			}

			if (graphData && createdGraphLines) {
				callGraphData.add(callGraphFactory
						.getCallGraphData(callGraphDataLines));
				createdGraphLines = false;
				callGraphDataLines = "";
			}

			if (line.equals("Index by function name")) {
				functionMapping = true;
				continue;
			}

			if (functionMapping) {
				if (!line.equals("")) {
					methodMappingData.addAll(methodMappingDataFactory
							.getMethodMapping(line));
				}
			}

		}

		return new MethodData(methodData, callGraphData, methodMappingData);
	}
}
